package com.bluesky.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bluesky.common.Constants;
import com.bluesky.common.enums.*;
import com.bluesky.common.exception.CustomException;
import com.bluesky.common.utils.SecurityUtils;
import com.bluesky.system.common.dto.SysTenantAddDTO;
import com.bluesky.system.common.dto.SysTenantEditDTO;
import com.bluesky.system.common.dto.SysTenantQueryDTO;
import com.bluesky.system.entity.SysRole;
import com.bluesky.system.entity.SysTenant;
import com.bluesky.system.entity.SysUser;
import com.bluesky.system.entity.SysUserRole;
import com.bluesky.system.mapper.SysTenantMapper;
import com.bluesky.system.service.*;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 租户表 服务实现类
 * </p>
 *
 * @author Kevin
 * @since 2021-09-29
 */
@Service
public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant> implements ISysTenantService {

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private ISysRoleService sysRoleService;

    @Resource
    private ISysUserService sysUserService;

    @Resource
    private ISysUserRoleService sysUserRoleService;

    @Resource
    private ISysConfigService sysConfigService;

    @Override
    public IPage<SysTenant> page(Page reqPage, SysTenantQueryDTO req) {
        LambdaQueryWrapper<SysTenant> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.like(StrUtil.isNotBlank(req.getTenantCode()), SysTenant::getTenantCode, req.getTenantCode());
        queryWrapper.like(StrUtil.isNotBlank(req.getTenantName()), SysTenant::getTenantName, req.getTenantName());
        return this.page(reqPage, queryWrapper);
    }

    @Override
    public List<SysTenant> list(SysTenantQueryDTO req) {
        LambdaQueryWrapper<SysTenant> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.like(StrUtil.isNotBlank(req.getTenantCode()), SysTenant::getTenantCode, req.getTenantCode());
        queryWrapper.like(StrUtil.isNotBlank(req.getTenantName()), SysTenant::getTenantName, req.getTenantName());
        return this.list(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(SysTenantAddDTO req) {
        if (!this.checkUniqueTenantCode(req.getTenantCode(), null)) {
            throw new CustomException("租户编码已存在");
        }
        if (!this.checkUniqueTenantName(req.getTenantName(), null)) {
            throw new CustomException("租户名称已存在");
        }
        SysTenant entity = BeanUtil.copyProperties(req, SysTenant.class);
        this.save(entity);
        // 新建租户对应的默认角色
        SysRole sysRole = new SysRole();
        sysRole.setTenantId(entity.getId());
        sysRole.setRoleCode("admin");
        sysRole.setRoleName("管理员");
        sysRole.setDataScope(DataScopeEnum.ALL.getCode());
        sysRole.setSort(1);
        sysRole.setStatus(StatusEnum.YES.getCode());
        sysRoleService.save(sysRole);
        // 新建租户对应的默认用户
        SysUser sysUser = new SysUser();
        sysUser.setTenantId(entity.getId());
        sysUser.setAccount("admin");
        // 获取默认密码
        String defaultPassword = sysConfigService.getConfigValueByKey("sys_init_password");
        sysUser.setPassword(passwordEncoder.encode(defaultPassword));
        sysUser.setPswModified(PswModifiedEnum.NO.getCode());
        sysUser.setNickname("管理员");
        sysUser.setRealname("管理员");
        sysUser.setEnglishName("admin");
        sysUser.setSex(SexEnum.MAN.getCode());
        sysUser.setLockFlag(LockFlagEnum.NORMAL.getCode());
        sysUser.setSort(1);
        sysUser.setStatus(StatusEnum.YES.getCode());
        sysUser.setDelFlag(DelFlagEnum.NO.getCode());
        sysUserService.save(sysUser);
        // 新建租户角色和用户的关联关系
        SysUserRole sysUserRole = new SysUserRole();
        sysUserRole.setUserId(sysUser.getId());
        sysUserRole.setRoleId(sysRole.getId());
        sysUserRoleService.save(sysUserRole);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(SysTenantEditDTO req) {
        if (!this.checkUniqueTenantCode(req.getTenantCode(), req.getId())) {
            throw new CustomException("租户编码已存在");
        }
        if (!this.checkUniqueTenantName(req.getTenantName(), req.getId())) {
            throw new CustomException("租户名称已存在");
        }
        SysTenant entity = BeanUtil.copyProperties(req, SysTenant.class);
        this.updateById(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(String ids) {
        this.removeByIds(Arrays.asList(ids.split(",")));
    }

    @Override
    public SysTenant view(String id) {
        return this.getById(id);
    }

    private Boolean checkUniqueTenantCode(String value, Long id) {
        if (StrUtil.isBlank(value)) {
            return true;
        }
        id = Objects.isNull(id) ? -1L : id;
        SysTenant entity = this.getOne(Wrappers.lambdaQuery(SysTenant.class).eq(SysTenant::getTenantCode, value));
        return Objects.isNull(entity) || entity.getId().longValue() == id.longValue();
    }

    private Boolean checkUniqueTenantName(String value, Long id) {
        if (StrUtil.isBlank(value)) {
            return true;
        }
        id = Objects.isNull(id) ? -1L : id;
        SysTenant entity = this.getOne(Wrappers.lambdaQuery(SysTenant.class).eq(SysTenant::getTenantName, value));
        return Objects.isNull(entity) || entity.getId().longValue() == id.longValue();
    }

    @Override
    public List<SysTenant> select() {
        LambdaQueryWrapper<SysTenant> queryWrapper = Wrappers.lambdaQuery();
        if (!SecurityUtils.getTenantCode().equals(Constants.ADMIN_TENANT)) {
            queryWrapper.eq(SysTenant::getId, SecurityUtils.getTenantId());
        }
        return this.list(queryWrapper);
    }

}
